#region Copyright (C) 2007 Jens Winter

//Copyright (C) 2007 Jens Winter

//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU Lesser General Public
//License as published by the Free Software Foundation; either
//version 2.1 of the License, or (at your option) any later version.

//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//Lesser General Public License for more details.

//You should have received a copy of the GNU Lesser General Public
//License along with this library; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#endregion

using System;
using System.Data;
using System.Linq;
using Flynn.Core.Activities;
using Flynn.Core.ActivityResults;
using Flynn.Core.TaskResults;
using Flynn.Core.Tasks;

namespace Flynn.Core.Tasks
{
    public class UpdateDatabaseTask : IUpdateDatabaseTask
    {
        private readonly IGetCurrentVersionActivity _getCurrentVersionActivity;
        private readonly IFilterAndExecuteUpdatesActivity _filterAndExecuteUpdatesActivity;
        private readonly ISetCurrentVersionActivity _setCurrentVersionActivity;

        public UpdateDatabaseTask(IGetCurrentVersionActivity getCurrentVersionActivity, IFilterAndExecuteUpdatesActivity filterAndExecuteUpdatesActivity, ISetCurrentVersionActivity setCurrentVersionActivity)
        {
            if (getCurrentVersionActivity == null)
                throw new ArgumentNullException("getCurrentVersionActivity");

            if (filterAndExecuteUpdatesActivity == null)
                throw new ArgumentNullException("filterAndExecuteUpdatesActivity");

            if (setCurrentVersionActivity == null)
                throw new ArgumentNullException("setCurrentVersionActivity");

            _getCurrentVersionActivity = getCurrentVersionActivity;
            _filterAndExecuteUpdatesActivity = filterAndExecuteUpdatesActivity;
            _setCurrentVersionActivity = setCurrentVersionActivity;
        }

        public UpdatingDatabaseResult UpdateDatabase(Project project, string toVersion, IDbConnection connection)
        {
            if (project == null)
                throw new ArgumentNullException("project");

            if (connection == null)
                throw new ArgumentNullException("connection");

            try
            {
                GettingCurrentVersionResult gettingCurrentVersionResult = _getCurrentVersionActivity.GetCurrentVersion(project, connection);
                if (gettingCurrentVersionResult.Failed)
                    return UpdatingDatabaseResult.Failure(gettingCurrentVersionResult.FailureMessage);

                string currentVersion = gettingCurrentVersionResult.CurrentVersion;

                FilterAndExecuteUpdatesResult filterAndExecuteUpdatesResult = _filterAndExecuteUpdatesActivity.FilterAndExecuteUpdates(project, currentVersion, toVersion, connection);
                if (filterAndExecuteUpdatesResult.Failed)
                    return UpdatingDatabaseResult.Failure(filterAndExecuteUpdatesResult.FailureMessage);

                if (filterAndExecuteUpdatesResult.ExecutedUpdates.Count() > 0)
                {
                    string targetVersion = filterAndExecuteUpdatesResult.ExecutedUpdates.Last().Version;

                    SettingCurrentVersionResult settingCurrentVersionResult = _setCurrentVersionActivity.SetCurrentVersion(project, targetVersion, connection);
                    if (settingCurrentVersionResult.Failed)
                        return UpdatingDatabaseResult.Failure(settingCurrentVersionResult.FailureMessage);

                    return UpdatingDatabaseResult.Success(filterAndExecuteUpdatesResult.ExecutedUpdates.Count(), gettingCurrentVersionResult.CurrentVersion, targetVersion);
                }
                else
                    return UpdatingDatabaseResult.Success(0, gettingCurrentVersionResult.CurrentVersion, gettingCurrentVersionResult.CurrentVersion);
            }
            catch (Exception e)
            {
                return UpdatingDatabaseResult.Failure(e.Message);
            }
        }
    }
}